package com.pesking.core.sqlparser;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson.JSON;
import com.pesking.core.Configure;
import com.pesking.core.LoadResourceStreamCallback;
import com.pesking.core.SpringBeanUtils;
import com.pesking.core.cache.Cache;
import com.pesking.core.cache.CacheExpireTimeType;
import com.pesking.core.cache.CacheManager;
import com.pesking.core.datasource.DatasourceManage;
import com.pesking.core.datasource.NotReturnConnectionCallback;
import com.pesking.core.datasource.Page;
import com.pesking.core.freemarker.FreemarkerManage;
import com.pesking.core.parameter.JsonRequestParameter;
import com.pesking.core.parameter.Parameter;
import com.pesking.core.util.*;

/**
 * SQL解释器管理器
 * @author cypei
 * @since 4.0
 */
public class SqlParserManage {

	/**
	 * 对象转换为参数parameter
	 * @param o			普通对象
	 * @return			返回参数对象
	 */
	public static Parameter toParameter(Object o){
		Parameter p = new Parameter();
		if (o != null){
			String json = JSON.toJSONString(o);
			JsonRequestParameter.jsonToParameter(json,p);
		}
		return p;
	}

	/**
	 * 执行更新
	 * @param statementById			SQL语句ID
	 * @param parameter				参数对象
	 * @return						更新成功返回1，否则返回 0
	 */
	public static int updateById(String statementById,Parameter parameter) {
		return updateById(null,statementById,parameter);
	}

	/**
	 * 执行更新
	 * @param datasourceName		数据源名称
	 * @param statementById			SQL语句ID
	 * @param parameter				参数对象
	 * @return						更新成功返回1，否则返回 0
	 */
	public static int updateById(String datasourceName
			,String statementById
			,Parameter parameter) {
		String statement = getStatementById(statementById);
		return update(datasourceName,statement,parameter);
	}
	
	/**
	 * 执行更新
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						更新成功返回1，否则返回 0
	 */
	public static int update(String statement,Parameter parameter) {
		return update(null,statement,parameter);
	}

	/**
	 * 执行更新
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						更新成功返回1，否则返回 0
	 */
	public static int update(String datasourceName
												,String statement
												,Parameter parameter) {
		UpdateSqlResult result = new UpdateSqlResult(parameter);
		execute(datasourceName,statement,parameter,result,null);
		return result.getResult();
	}
	
	/**
	 * 以新的事务执行更新
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 */
	public static void updateByNewTransaction(String statement,Parameter parameter) {
		updateByNewTransaction(null,statement,parameter);
	}

	/**
	 * 以新的事务执行更新
	 * @param datasourceName		数据源名称
	 * @param statementId			SQL语句ID
	 * @param parameter				参数对象
	 */
	public static void updateByNewTransactionById(String datasourceName,String statementId,Parameter parameter) {
		String statement = getStatementById(statementId);
		updateByNewTransaction(datasourceName,statement,parameter);
	}

	/**
	 * 以新的事务执行更新
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 */
	public static void updateByNewTransaction(String datasourceName,String statement,Parameter parameter) {
		DatasourceManage.startNewTransaction(datasourceName, new NotReturnConnectionCallback() {

			@Override
			public void execute(Connection connection) {
				UpdateSqlResult result = new UpdateSqlResult(parameter);
				getSqlParser().executeSQL(connection, statement, parameter, null, result);
				LogUtils.debug("更新结果状态--->" + result.getResult());
			}
			
		});
	}

	/**
	 * 执行查询
	 * @param statement				SQL语句
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapList(String statement) {
		return toMapList(statement,null);
	}

	/**
	 * 执行查询
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapList(String statement
												,Parameter parameter) {
		return toMapList(null,statement,parameter);
	}

	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapList(String datasourceName
												,String statement
												,Parameter parameter) {
		return toMapList(datasourceName,statement,parameter,null);
	}
	
	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapList(String datasourceName
												,String statement
												,Parameter parameter
												,Page page) {
		MapListSqlResult result = new MapListSqlResult(parameter);
		execute(datasourceName,statement,parameter,result,page);
		List<Map<String,String>> rtn = result.getResult();
		//LogUtils.info("<<<<<<<<SQL->" + statement + " 结果列表->" + rtn);
		if (rtn == null) {
			rtn = new ArrayList<>(1);
		}
		
		return result.getResult();
	}

	/**
	 * 执行查询
	 * @param statementById			SQL语句ID
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapListById(String statementById) {
		return toMapListById(statementById,null);
	}

	/**
	 * 执行查询
	 * @param statementById				SQL语句ID
	 * @param parameter				参数对象
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapListById(String statementById
			,Parameter parameter) {
		return toMapListById(null,statementById,parameter);
	}

	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statementById			SQL语句ID
	 * @param parameter				参数对象
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapListById(String datasourceName
			,String statementById
			,Parameter parameter) {
		return toMapListById(datasourceName,statementById,parameter,null);
	}

	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statementById			SQL语句ID
	 * @param parameter				参数对象
	 * @return						键值对列表
	 */
	public static List<Map<String,String>> toMapListById(String datasourceName
			,String statementById
			,Parameter parameter
			,Page page) {
		String statement = getStatementById(statementById);
		return toMapList(datasourceName,statement,parameter,page);
	}

	/**
	 * 执行查询
	 * @param statement				SQL语句
	 * @return						字符串列表
	 */
	public static List<String>	toSingleFieldList(String statement) {
		return toSingleFieldList(statement,null);
	}
	
	/**
	 * 执行查询
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						字符串列表
	 */
	public static List<String> toSingleFieldList(String statement
												,Parameter parameter) {
		return toSingleFieldList(null,statement,parameter);
	}
	
	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						字符串列表
	 */
	public static List<String> toSingleFieldList(String datasourceName
												,String statement
												,Parameter parameter) {
		SingleFieldListSqlResult result = new SingleFieldListSqlResult(parameter);
		execute(datasourceName,statement,parameter,result,null);
		List<String> rtn = result.getResult();
		
		if (rtn == null) {
			rtn = new ArrayList<>(1);
		}
		
		return rtn;
	}

	/**
	 * 执行查询
	 * @param statementId				SQL语句ID
	 * @return						字符串列表
	 */
	public static List<String>	toSingleFieldListById(String statementId) {
		return toSingleFieldListById(statementId,null);
	}

	/**
	 * 执行查询
	 * @param statementId				SQL语句ID
	 * @param parameter				参数对象
	 * @return						字符串列表
	 */
	public static List<String> toSingleFieldListById(String statementId
			,Parameter parameter) {
		return toSingleFieldListById(null,statementId,parameter);
	}

	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statementId				SQL语句ID
	 * @param parameter				参数对象
	 * @return						字符串列表
	 */
	public static List<String> toSingleFieldListById(String datasourceName
			,String statementId
			,Parameter parameter) {
		String statement = getStatementById(statementId);
		return toSingleFieldList(datasourceName,statement,parameter);
	}

	/**
	 * 执行查询，输出对象列表
	 * @param statement					SQL语句
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> List<T> toObjectList(String statement,Class<T> resultClass) {
		return toObjectList(statement,null,resultClass);
	}


	/**
	 * 执行查询，输出对象列表
	 * @param statement					SQL语句
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> List<T> toObjectList(String statement
												,Parameter parameter
												,Class<T> resultClass) {
		return toObjectList(null,statement,parameter,resultClass);
	}

	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						数据列表对象
	 */
	public static <T> List<T> toObjectList(String datasourceName
			,String statement
			,Parameter parameter
			,Class<T> resultClass) {
		return toObjectList(datasourceName,statement,parameter,resultClass,null);
	}

	/**
	 * 执行查询，输出对象列表
	 * @param datasourceName			数据源名
	 * @param statement					SQL语句
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @param page						分页对象
	 * @return							返回列表对象
	 */
	public static <T> List<T> toObjectList(String datasourceName,String statement,Parameter parameter,Class<T> resultClass,Page page){
		MapListSqlResult result = new MapListSqlResult(parameter);
		execute(datasourceName,statement,parameter,result,page);
		List<T> rtn = new ArrayList<>();
		List<Map<String,String>> data = result.getResult();
		if (data != null){
			data.forEach(item -> {
				rtn.add(mapToObject(item,resultClass));
			});
		}
		return rtn;
	}

	/**
	 * 执行查询，输出对象列表
	 * @param statementId					SQL语句ID
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> List<T> toObjectListById(String statementId,Class<T> resultClass) {
		return toObjectListById(statementId,null,resultClass);
	}

	/**
	 * 执行查询，输出对象列表
	 * @param statementId					SQL语句ID
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> List<T> toObjectListById(String statementId
			,Parameter parameter
			,Class<T> resultClass) {
		return toObjectListById(null,statementId,parameter,resultClass,null);
	}

	/**
	 * 执行查询
	 * @param datasourceName		数据源名称
	 * @param statementId			SQL语句ID
	 * @param parameter				参数对象
	 * @return						数据列表对象
	 */
	public static <T> List<T> toObjectListById(String datasourceName
			,String statementId
			,Parameter parameter
			,Class<T> resultClass) {
		return toObjectListById(datasourceName,statementId,parameter,resultClass,null);
	}


	/**
	 * 执行查询，输出对象列表
	 * @param datasourceName			数据源名
	 * @param statementId					SQL语句ID
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @param page						分页对象
	 * @return							返回列表对象
	 */
	public static <T> List<T> toObjectListById(String datasourceName,String statementId,Parameter parameter,Class<T> resultClass,Page page){
		String statement = getStatementById(statementId);
		return toObjectList(datasourceName,statement,parameter,resultClass,page);
	}

	/**
	 * 执行查询，输出指定对象
	 * @param statement					SQL语句
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> T toObject(String statement,Class<T> resultClass) {
		return toObject(statement,null,resultClass);
	}


	/**
	 * 执行查询，输出指定对象
	 * @param statement					SQL语句
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> T toObject(String statement
			,Parameter parameter
			,Class<T> resultClass) {
		return toObject(null,statement,parameter,resultClass);
	}

	/**
	 * 执行查询，输出指定对象
	 * @param datasourceName		数据源名称
	 * @param statement				SQL语句
	 * @param parameter				参数对象
	 * @return						数据列表对象
	 */
	public static <T> T toObject(String datasourceName
			,String statement
			,Parameter parameter
			,Class<T> resultClass) {
		return toObject(datasourceName,statement,parameter,resultClass,null);
	}

	/**
	 * 执行查询，输出指定对象
	 * @param datasourceName			数据源名
	 * @param statement					SQL语句
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @param page						分页对象
	 * @return							返回列表对象
	 */
	public static <T> T toObject(String datasourceName,String statement,Parameter parameter,Class<T> resultClass,Page page){
		MapListSqlResult result = new MapListSqlResult(parameter);
		execute(datasourceName,statement,parameter,result,page);
		List<Map<String,String>> data = result.getResult();
		if (data != null && !data.isEmpty()){
			Map<String,String> map = data.get(0);
			return mapToObject(map,resultClass);
		}
		return null;
	}

	/**
	 * 执行查询，输出指定对象
	 * @param statementId					SQL语句ID
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> T toObjectById(String statementId,Class<T> resultClass) {
		return toObjectById(statementId,null,resultClass);
	}

	/**
	 * 执行查询，输出指定对象
	 * @param statementId					SQL语句ID
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @return							返回列表对象
	 */
	public static <T> T toObjectById(String statementId
			,Parameter parameter
			,Class<T> resultClass) {
		return toObjectById(null,statementId,parameter,resultClass,null);
	}

	/**
	 * 执行查询，输出指定对象
	 * @param datasourceName		数据源名称
	 * @param statementId			SQL语句ID
	 * @param parameter				参数对象
	 * @return						数据列表对象
	 */
	public static <T> T toObjectById(String datasourceName
			,String statementId
			,Parameter parameter
			,Class<T> resultClass) {
		return toObjectById(datasourceName,statementId,parameter,resultClass,null);
	}


	/**
	 * 执行查询，输出指定对象
	 * @param datasourceName			数据源名
	 * @param statementId					SQL语句ID
	 * @param parameter					参数对象
	 * @param resultClass				返回结果类型
	 * @param page						分页对象
	 * @return							返回列表对象
	 */
	public static <T> T toObjectById(String datasourceName,String statementId,Parameter parameter,Class<T> resultClass,Page page){
		String statement = getStatementById(statementId);
		return toObject(datasourceName,statement,parameter,resultClass,page);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param statement				sql语句
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObject(String statement,ResultConvertCallback<T> callback,T result) {
		mapToObject(statement,(Parameter)null,callback,result);
	}
	
	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param statement				sql语句
	 * @param parameter				参数对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObject(String statement,Parameter parameter,ResultConvertCallback<T> callback,T result) {
		mapToObject(null,statement,parameter,callback,result);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statement				sql语句
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObject(String datasourceName,String statement,ResultConvertCallback<T> callback,T result) {
		mapToObject(datasourceName,statement,null,callback,result);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statement				sql语句
	 * @param parameter				参数对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObject(String datasourceName,String statement,Parameter parameter,ResultConvertCallback<T> callback,T result) {
		mapToObject(datasourceName,statement,parameter,null,callback,result,null);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statement				sql语句
	 * @param parameter				参数对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 * @param cacheKeyTemplate		缓存key模板
	 */
	public static <T> void mapToObject(String datasourceName,String statement,Parameter parameter,ResultConvertCallback<T> callback,T result,String cacheKeyTemplate) {
		mapToObject(datasourceName,statement,parameter,null,callback,result,cacheKeyTemplate);
	}
	
	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statement				sql语句
	 * @param parameter				参数对象
	 * @param page					分页对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 * @param cacheKeyTemplate		缓存key模板
	 */
	public static <T> void mapToObject(String datasourceName,String statement,Parameter parameter,Page page,ResultConvertCallback<T> callback,T result,String cacheKeyTemplate) {
		List<Map<String,String>> mapList = null;
		String cacheKey = null;
		Cache<ListMapCacheObject> cache = null;
		if (!StringUtils.isBlank(cacheKeyTemplate)) {
			cacheKey = FreemarkerManage.parseTemplate(cacheKeyTemplate, parameter);
			cache = CacheManager.getLocalCacheManager().getCache("sql_parser_map_list_cache", ListMapCacheObject.class, 120, CacheExpireTimeType.FIX_TIME);
			ListMapCacheObject cacheObject = cache.get(cacheKey);
			if (cacheObject != null) {
				mapList = cacheObject.getData();
				if (mapList != null) {
					LogUtils.info("根据缓存key[" + cacheKey + "]命中缓存数据...................");
				}
			}			
		}
		if (mapList == null) {
			mapList = toMapList(datasourceName,statement,parameter,page);
		}
		if (mapList != null && cache != null) {
			ListMapCacheObject co = new ListMapCacheObject();
			co.setData(mapList);
			cache.set(cacheKey, co);
		}
		callback.toResult(mapList,result);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param statementId				sql语句
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObjectById(String statementId,ResultConvertCallback<T> callback,T result) {
		mapToObjectById(statementId,(Parameter)null,callback,result);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param statementId				sql语句
	 * @param parameter				参数对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObjectById(String statementId,Parameter parameter,ResultConvertCallback<T> callback,T result) {
		mapToObjectById(null,statementId,parameter,callback,result);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statementId				sql语句
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObjectById(String datasourceName,String statementId,ResultConvertCallback<T> callback,T result) {
		mapToObjectById(datasourceName,statementId,null,callback,result);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statementId				sql语句
	 * @param parameter				参数对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 */
	public static <T> void mapToObjectById(String datasourceName,String statementId,Parameter parameter,ResultConvertCallback<T> callback,T result) {
		mapToObjectById(datasourceName,statementId,parameter,null,callback,result,null);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statementId				sql语句
	 * @param parameter				参数对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 * @param cacheKeyTemplate		缓存key模板
	 */
	public static <T> void mapToObjectById(String datasourceName,String statementId,Parameter parameter,ResultConvertCallback<T> callback,T result,String cacheKeyTemplate) {
		mapToObjectById(datasourceName,statementId,parameter,null,callback,result,cacheKeyTemplate);
	}

	/**
	 * 执行查询，把map对象转换为指定对象值
	 * @param datasourceName		数据源名称
	 * @param statementId				sql语句
	 * @param parameter				参数对象
	 * @param page					分页对象
	 * @param callback				回调对象
	 * @param result				输出对象
	 * @param cacheKeyTemplate		缓存key模板
	 */
	public static <T> void mapToObjectById(String datasourceName,String statementId,Parameter parameter,Page page,ResultConvertCallback<T> callback,T result,String cacheKeyTemplate) {
		String statement = getStatementById(statementId);
		mapToObject(datasourceName,statement,parameter,page,callback,result,cacheKeyTemplate);
	}
	
	/**
	 * 求总记录数
	 * @param statement 		统计类SQL
	 * @return					总记录数
	 */
	public static long getTotalCountByTotalCountSql(String statement) {
		return getTotalCountByTotalCountSql(statement,null);
	}
	
	/**
	 * 求总记录数
	 * @param statement 		统计类SQL
	 * @param parameter			参数对象
	 * @return					总记录数
	 */
	public static long getTotalCountByTotalCountSql(String statement,Parameter parameter) {
		return getTotalCountByTotalCountSql(null,statement,parameter);
	}
	
	/**
	 * 求总记录数
	 * @param datasourceName	数据源名称
	 * @param statement 		统计类SQL
	 * @param parameter			参数对象
	 * @return					总记录数
	 */
	public static long getTotalCountByTotalCountSql(String datasourceName,String statement,Parameter parameter) {
		List<String> list = toSingleFieldList(datasourceName,statement,parameter);
		if (!list.isEmpty()) {
			return Long.parseLong(list.get(0));
		}
		return 0L;
	}

	/**
	 * 求总记录数
	 * @param statementId 		统计类SQL
	 * @return					总记录数
	 */
	public static long getTotalCountByTotalCountSqlId(String statementId) {
		return getTotalCountByTotalCountSqlId(statementId,null);
	}

	/**
	 * 求总记录数
	 * @param statementId 		统计类SQL
	 * @param parameter			参数对象
	 * @return					总记录数
	 */
	public static long getTotalCountByTotalCountSqlId(String statementId,Parameter parameter) {
		return getTotalCountByTotalCountSqlId(null,statementId,parameter);
	}

	/**
	 * 求总记录数
	 * @param datasourceName	数据源名称
	 * @param statementId 		统计类SQL
	 * @param parameter			参数对象
	 * @return					总记录数
	 */
	public static long getTotalCountByTotalCountSqlId(String datasourceName,String statementId,Parameter parameter) {
		String statement = getStatementById(statementId);
		return getTotalCountByTotalCountSql(datasourceName,statement,parameter);
	}

	/**
	 * 求总记录数
	 * @param statement 		统计类SQL
	 * @return					返回总记录数
	 */
	public static long getTotalCountBySql(String statement) {
		return getTotalCountBySql(statement,null);
	}

	/**
	 * 求总记录数
	 * @param statementId 		统计类SQL
	 * @param parameter			参数对象
	 * @return					返回总记录数
	 */
	public static long getTotalCountBySqlId(String statementId,Parameter parameter) {
		String statement = getStatementById(statementId);
		return getTotalCountBySql(statement,parameter);
	}

	/**
	 * 求总记录数
	 * @param statement 		统计类SQL
	 * @param parameter			参数对象
	 * @return					返回总记录数
	 */
	public static long getTotalCountBySql(String statement,Parameter parameter) {
		return getTotalCountBySql(null,statement,parameter);
	}

	/**
	 * 求总记录数
	 * @param datasourceName	数据源名称
	 * @param statementId 		统计类SQLId
	 * @param parameter			参数对象
	 * @return					返回总记录数
	 */
	public static long getTotalCountBySqlId(String datasourceName,String statementId,Parameter parameter) {
		String statement = getStatementById(statementId);
		return getTotalCountBySql(datasourceName,statement,parameter);
	}
	
	/**
	 * 求总记录数
	 * @param datasourceName	数据源名称
	 * @param statement 		统计类SQL
	 * @param parameter			参数对象
	 * @return					返回总记录数
	 */
	public static long getTotalCountBySql(String datasourceName,String statement,Parameter parameter) {
		String totalSQL = FreemarkerManage.parseTemplate(statement, parameter);
		
		if (totalSQL.toLowerCase().contains("union")
				|| totalSQL.toLowerCase().contains("group")){
			LogUtils.debug( "SQL语句中存在union语句，采取传统方式.");
			totalSQL = "select count(1) cnt from (" + totalSQL + ") a";
		}
		else{
			Map<String,String> regMap = new HashMap<String,String>();
			regMap.put("order\\s+by[\\sa-zA-Z0-9,_.\\(\\)]+\\)",")");
			regMap.put("order\\s+by[\\sa-zA-Z0-9,_.\\(\\)]+","");
            for (String reg : regMap.keySet()) {
                String value = regMap.get(reg);
                Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
                Matcher matcher = pattern.matcher(totalSQL);
                totalSQL = matcher.replaceAll(value);
            }
			totalSQL = getTotalCountSQL(totalSQL);
		}
		if (LogUtils.isDebugEnabled()) {
			LogUtils.debug("生成的求总记录数的SQL->" + totalSQL);
		}
		List<String> list = toSingleFieldList(datasourceName,totalSQL,parameter);
		if (!list.isEmpty()) {
			return Long.parseLong(list.get(0));
		}
		return 0L;
	}

	/**
	 * 借助SQL查询，把结果转化为值名称键值对输出
	 * @param sqlId					SQLID
	 * @param valueField			值字段名
	 * @param nameField				名称字段名
	 * @return						返回键值对象集合对象
	 */
	public static Map<String, String> toValueNameMapById(String sqlId,String valueField, String nameField) {
		String sql = getStatementById(sqlId);
		return toValueNameMap(null,sqlId,valueField,nameField);
	}
	
	/**
	 * 借助SQL查询，把结果转化为值名称键值对输出
	 * @param sql					SQL
	 * @param valueField			值字段名
	 * @param nameField				名称字段名
	 * @return						返回键值对象集合对象
	 */
	public static Map<String, String> toValueNameMap(String sql,String valueField, String nameField) {
		return toValueNameMap(null,sql,valueField,nameField);
	}

	/**
	 * 借助SQL查询，把结果转化为值名称键值对输出
	 * @param datasourceName		数据源名称
	 * @param sqlId					sqlId
	 * @param valueField			值字段名
	 * @param nameField				名称字段名
	 * @return						返回键值对象集合对象
	 */
	public static Map<String, String> toValueNameMapById(String datasourceName,String sqlId,String valueField, String nameField) {
		String sql = getStatementById(sqlId);
		return toValueNameMap(datasourceName,sql,valueField, nameField);
	}
	
	/**
	 * 借助SQL查询，把结果转化为值名称键值对输出
	 * @param datasourceName		数据源名称
	 * @param sql					sql
	 * @param valueField			值字段名
	 * @param nameField				名称字段名
	 * @return						返回键值对象集合对象
	 */
	public static Map<String, String> toValueNameMap(String datasourceName,String sql,String valueField, String nameField) {
		return toValueNameMap(datasourceName,sql,null,valueField,nameField);
	}

	/**
	 * 借助SQL查询，把结果转化为值名称键值对输出
	 * @param datasourceName				数据源名称
	 * @param sqlId						sqlId
	 * @param parameter					参数对象
	 * @param valueField				值字段名
	 * @param nameField					名称字段名
	 * @return							返回键值对象集合对象
	 */
	public static Map<String, String> toValueNameMapById(String datasourceName,String sqlId, Parameter parameter,String valueField, String nameField) {
		String sql = getStatementById(sqlId);
		return toValueNameMap(datasourceName,sql, parameter,valueField, nameField);
	}

	/**
	 * 借助SQL查询，把结果转化为值名称键值对输出
	 * @param datasourceName				数据源名称
	 * @param sql						sql
	 * @param parameter					参数对象
	 * @param valueField				值字段名
	 * @param nameField					名称字段名
	 * @return							返回键值对象集合对象
	 */
	public static Map<String, String> toValueNameMap(String datasourceName,String sql, Parameter parameter,String valueField, String nameField) {
		Map<String,String> result = new HashMap<>();
		List<Map<String,String>> rtn = toMapList(datasourceName,sql,parameter);
		if (rtn != null && !rtn.isEmpty()) {
			Map<String,String> map = rtn.get(0);
			if (StringUtils.isBlank(valueField) || StringUtils.isBlank(nameField)) {
				Set<String> keys = map.keySet();
				if (!keys.isEmpty()) {
					Iterator<String> it = keys.iterator();
					valueField = it.next();
					if (it.hasNext()) {
						nameField = it.next();
					}
					else {
						nameField = valueField;
					}
				}
			}

            for (Map<String, String> stringStringMap : rtn) {
                map = stringStringMap;
                String value = map.get(valueField);
                String name = map.get(nameField);
                result.put(value, name);
            }
		}
		return result;
	}
	
	private static String getTotalCountSQL(String sql){
		String resultSQL = "";
		String srcSQL = sql;
		int lastIndex = 0;
		sql = sql.toLowerCase();
		Stack<Integer> stack = new Stack<Integer>();
		while(true){
			int ind1 = sql.indexOf("select");
			int ind2 = sql.indexOf("from");
			int ind = -1;
			boolean selectFlag = false;
			if (ind1 != -1 && ind2 != -1){
				//两者都存在
				if (ind1 < ind2){
					selectFlag = true;
					ind = ind1;
				}
				else{
					ind = ind2;
				}
			}
			else if (ind1 != -1){
				ind = ind1;
				selectFlag = true;
			}
			else if (ind2 != -1){
				ind = ind2;
			}
			
			if (ind == -1){
				break;
			}
			else{
				lastIndex += sql.substring(0, ind + (selectFlag ? "select".length() : "from".length())).length();
				sql = sql.substring(ind + (selectFlag ? "select".length() : "from".length()));
				
				if (selectFlag){
					stack.push(ind);
				}
				else{
					if (stack.size() == 1){
						//表示只有一个select了
						int index = stack.pop();
						resultSQL = srcSQL.substring(0, index + "select".length())
								+ " count(1) total "
								+ srcSQL.substring(lastIndex - 4);
						break;
					}
					else{
						stack.pop();
					}
				}
			}
		}
		return resultSQL;
	}

	private static <T> void execute(String datasourceName,String statement,Parameter parameter,SqlResult<T> result,Page iPage) {
		final Parameter param;
		if (parameter == null) {
			param = ThreadUtils.getCurrentParameter();
		}
		else {
			param = parameter;
		}
		DatasourceManage.executeSQL(datasourceName,new NotReturnConnectionCallback() {

			@Override
			public void execute(Connection connection) {
                boolean totalCountFlag = "true".equals(param.getParameter("total_count_flag"));
				if (iPage != null && totalCountFlag) {
					String strTotalCount = param.getParameter("total_count");
					Long totalCount = null;
					if (!StringUtils.isBlank(strTotalCount)) {
						totalCount = Long.valueOf(strTotalCount);
					}
					
					if (totalCount == null) {
						totalCount = getTotalCountBySql(datasourceName,statement,parameter);							
					}
					
					iPage.setTotalCount(totalCount);
				}				
				
				if (iPage != null) {
					getSqlParser().executeSQL(connection, statement, param, iPage, result);
				}
				else {
					getSqlParser().executeSQL(connection, statement, param, iPage, result);
				}
			}
			
		});
		//LogUtils.performanceTrace("<<<<<<<SQL->" + statement + " 结果列表->" + result);
	}

	private static String getStatementById(String statementId){
		String statement = null;
		String filePath = "/config/sql/" + statementId + ".sql";
		statement = Configure.getResourceStream(filePath,new LoadResourceStreamCallback<String>(){

			@Override
			public String execute(InputStream in) {
				if (in != null){
					return FileUtils.readTxtFile(in,"UTF-8");
				}
				return null;
			}

		});
		return statement;
	}

	public static <T> T mapToObject(Map<String,String> data,Class<T> resultClass){
		T rtn = null;
		if (data == null){
			return null;
		}

		try {
			//把key转换为全部小写
			final Map<String,String> map = new HashMap<>();
			data.forEach((key, value) -> map.put(key.toLowerCase(), value));

			rtn = resultClass.getDeclaredConstructor().newInstance();
			Field[] fields = ClassUtils.getFields(resultClass);
            for (Field f : fields) {
                String name = f.getName().toLowerCase();
				String value = map.get(name);
				if (!StringUtils.isBlank(value)){
					String typeName = f.getType().getName();
					f.setAccessible(true);
					if (typeName.equals(String.class.getName())){
						f.set(rtn,value);
					}
					else if (typeName.equals(Integer.class.getName())){
						f.set(rtn,Integer.parseInt(value));
					}
					else if (typeName.equals(Long.class.getName())){
						f.set(rtn,Long.parseLong(value));
					}
					else if (typeName.equals(Float.class.getName())){
						f.set(rtn,Float.parseFloat(value));
					}
					else if (typeName.equals(Double.class.getName())){
						f.set(rtn,Double.parseDouble(value));
					}
					else if (typeName.equals(Boolean.class.getName())){
						f.set(rtn,Boolean.getBoolean(value));
					}
					else if (typeName.equals(Byte.class.getName())){
						f.set(rtn,Byte.parseByte(value));
					}
					else if ("char".equals(typeName)){
						f.set(rtn,value.charAt(0));
					}
					else if (typeName.equals("int")){
						f.setInt(rtn,Integer.parseInt(value));
					}
					else if (typeName.equals("long")){
						f.setLong(rtn,Long.parseLong(value));
					}
					else if (typeName.equals("float")){
						f.setFloat(rtn,Float.parseFloat(value));
					}
					else if (typeName.equals("double")){
						f.setDouble(rtn,Double.parseDouble(value));
					}
					else if (typeName.equals("boolean")){
						f.setBoolean(rtn,Boolean.getBoolean(value));
					}
					else if (typeName.equals("byte")){
						f.set(rtn,Byte.parseByte(value));
					}
					else if ("short".equals(typeName)){
						f.setShort(rtn,(short)Double.parseDouble(value));
					}
					else if (typeName.equals(Date.class.getName())){
						f.set(rtn,DateUtils.string2Date(value));
					}
					else if (typeName.equals(Timestamp.class.getName())){
						f.set(rtn,DateUtils.string2Timestamp(value));
					}
					else {
						LogUtils.error("该类型字段[" + typeName + "]无法识别，转换失败.");
					}
				}
            }
        }
		catch(Exception ex){
			throw new RuntimeException(ex);
		}
		return rtn;
	}
	
	private static SqlParser getSqlParser() {
		if (sqlParser == null) {
			List<SqlParser> list = SpringBeanUtils.getBeanList(SqlParser.class);
			if (list.size() > 1) {
				OrderUtils.sortByMax(list);
			}
			sqlParser = list.get(0);
		}
		
		return sqlParser;
	}
	
	private static SqlParser sqlParser = null;

	

	
}
